package com.librariy.view;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
/**
 * 用法同ImageView, 但是将图片渲染为圆形（可带边框）。
 * 
 * @author luchyu
 * */
public class CircleImageView extends androidx.appcompat.widget.AppCompatImageView{
    private static final String TAG = CircleImageView.class.getName();
    private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
    private final Paint mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG), mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private DisplayMetrics dm= Resources.getSystem().getDisplayMetrics();
    private ColorMatrixColorFilter mDisableColorFilter;
    private Bitmap mBitmap = null;

    public CircleImageView(Context context) {
        super(context);
        this.initialize();
    }

    public CircleImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        this.initialize();
    }

    public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.initialize();
    }

    private void initialize() {
        super.setScaleType(SCALE_TYPE);
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);
        this.mDisableColorFilter = new ColorMatrixColorFilter(cm);
        // 边框
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(Color.WHITE);
        mBorderPaint.setStrokeWidth(1*dm.density);
    }

    @Override
    public ScaleType getScaleType() {
        return SCALE_TYPE;
    }

    @Override
    public void setScaleType(ScaleType scaleType) {
        if (scaleType != SCALE_TYPE) {
            throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        synchronized (this) {
            Log.d(TAG, "onPreDraw("+mBitmap+")");
            if (mBitmap == null) {
                Rect r = new Rect();
                canvas.getClipBounds(r);
                r.offset(0, 0);
                int radius = Math.min(r.width(), r.height()) / 2;
                mBitmap = Bitmap.createBitmap(r.width(), r.height(), Bitmap.Config.ARGB_8888);
                Canvas c = new Canvas(mBitmap);
                Path mPath = new Path();
                mPath.addCircle(r.exactCenterX(), r.exactCenterY(), radius, Path.Direction.CCW);
                c.clipPath(mPath, Region.Op.REPLACE);
                super.onDraw(c);
                c.drawCircle(r.exactCenterX(), r.exactCenterY(), radius - mBorderPaint.getStrokeWidth() / 2, mBorderPaint);
            }
            mBitmapPaint.setColorFilter(isEnabled() ? null : mDisableColorFilter);
            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
            Log.d(TAG, "onPostDraw("+mBitmap+")");
        }
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.reset();
    }

    public int getBorderColor() {
        return mBorderPaint.getColor();
    }

    public void setBorderColor(int borderColor) {
        mBorderPaint.setColor(borderColor);
        this.reset();
    }

    public void setBorderWidth(int borderWidth) {
        mBorderPaint.setStrokeWidth(borderWidth);
        this.reset();
    }
    @Override
    public void setImageDrawable(Drawable drawable) {
        Log.d(TAG, "setImageDrawable("+drawable+")");
        super.setImageDrawable(drawable);
        this.reset();
    }

    @Override
    public void setImageResource(int resId) {
        Log.d(TAG, "setImageResource("+resId+")");
        super.setImageResource(resId);
        this.reset();
    }

    public void reset() {
        synchronized (this) {
            mBitmap = null;
            invalidate();
        }
    }
}
